package com.post.remote.client;

import java.util.Vector;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.Log;

import com.post.remote.IRemoteMessageHandler;
import com.post.remote.RemoteBase;
import com.post.remote.server.RemoteService;

public class RemoteClient extends RemoteBase {
    
    protected static final String TAG = "RaceClient";
    final int MAX_TRYAGAIN = 10;
    int tryAgain = 0;
    private Messenger reply;
    private Messenger messenger;
    private Context mContext;
    private Vector<IRemoteMessageHandler> mHandlerList          = new Vector<IRemoteMessageHandler>();
    private Handler handler = new Handler(Looper.getMainLooper()) {
 
        @Override
        public void handleMessage(final Message msg) {
            if (handler==null) {
                Log.w(TAG,"this client had disconnect");
                return;
            }
            final byte[] bytes = msg.getData().getByteArray(RemoteService.KEY_DATA_BYTES);
            if (bytes!=null){
                for(int i = 0; i < mHandlerList.size(); i++){
                    if(mHandlerList.get(i)  == null){
                        continue;
                    }
                    mHandlerList.get(i).handleMessage(msg.arg1,bytes);
                }
//
//                handler.post(new Runnable() {
//
//                    @Override
//                    public void run() {
//
//                    }
//                });
            }else{
                final String string = msg.getData().getString(RemoteService.KEY_DATA_JSON);
                if (!TextUtils.isEmpty(string)){
                    handler.post(new Runnable() {

                        @Override
                        public void run() {
                            for(int i = 0; i < mHandlerList.size(); i++){
                                if(mHandlerList.get(i)  == null){
                                    continue;
                                }
                                mHandlerList.get(i).handleMessage(string);
                            }
                        }
                    });
                }
            }
        }
          
    };
    ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceDisconnected(ComponentName name) {
            messenger = null;
            Log.w(TAG, "onServiceDisconnected:"+name);
            mHandlerList.removeAll(mHandlerList);
        }
         
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            messenger = new Messenger(service);
             Log.d(TAG, "bind success ->:"+name);
        }
    };

    
    public RemoteClient(Context pContext){
        this.mContext = pContext;
    }
    public RemoteClient(Context pContext,String pServicePackageName){
        this.mContext = pContext;
        RemoteBase.mServicePackageName= pServicePackageName;

    }
    public void disConnect() {
         Log.d(TAG, "disConnects ->messenger: "+messenger);
        handler.removeCallbacksAndMessages(null);
        handler = null;
        if (messenger!=null) {
            mContext.unbindService(conn);
            messenger = null;
        }
    }
    public void addListener(IRemoteMessageHandler pListener) {
        if (pListener == null) { throw new NullPointerException(" pListener can not be null"); }
         Log.d(TAG,"pListener:" + pListener);
        if (mHandlerList.contains(pListener)) {
            Log.w(TAG,"pListener had be add");
            return;
        }
        mHandlerList.add(pListener);
    }

    public void removeListener(IRemoteMessageHandler pListener) {
        if (pListener != null) {
            mHandlerList.remove(pListener);
        }
         Log.d(TAG,"Listener  size:" + mHandlerList.size());
    }
    public void sendMessage(final int pAction ,final byte[] pBytes) throws RemoteException {
        if(messenger == null){
            reply = new Messenger(handler);
            Intent intent = new Intent();
            intent.setClassName(mServicePackageName, "com.post.remote.server.RemoteService");
            getContext().bindService(intent, conn, Context.BIND_AUTO_CREATE);

        }
        if (messenger!=null){
            Message msg = creatMessage(reply,pAction, pBytes);
            messenger.send(msg);
            return;
        }
        handler.post(new Runnable() {

            @Override
            public void run() {
                if (messenger==null) {
                    tryAgain++;
                    if (tryAgain<MAX_TRYAGAIN) {
                        Log.w(TAG, "wait service connect,tryAgain is "+ tryAgain);
                        handler.postDelayed(this, 200);
                        return;
                    }else{
                        Log.w(TAG, "try timeout");
                        return;
                    }
                }
                Message msg = creatMessage(reply,pAction, pBytes);
                try {
                    messenger.send(msg);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                tryAgain = 0;
            }
        });
    }



    public void sendMessage(final String pMessage) {
        if(messenger == null){
            reply = new Messenger(handler);
            Intent intent = new Intent();
            intent.setClassName(mServicePackageName, "com.post.remote.server.RemoteService");
            getContext().bindService(intent, conn, Context.BIND_AUTO_CREATE);

        }
        handler.postDelayed(new Runnable() {
            
            @Override
            public void run() {
                if (messenger==null) {
                    tryAgain++;
                    if (tryAgain<MAX_TRYAGAIN) {
                        Log.w(TAG, "wait service connect,tryAgain is "+ tryAgain);
                        handler.postDelayed(this, 200);
                        return;
                    }else{
                        Log.w(TAG, "try timeout");
                        return;
                    }
                }
//                 Log.d(TAG, "sendMessage "+message);
                Message msg = Message.obtain(null, 1);
                msg.replyTo = reply;
                final Bundle data = new Bundle();
                data.putString("json", pMessage);
                msg.setData(data);
                try {
                    messenger.send(msg);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                tryAgain = 0;
            }
        }, 0);

    }
    
    
    
    /**
     * @return
     */
    private Context getContext() {
        return mContext;
    }
//    JSONObject data = new JSONObject();
//    data.put("score", new JSONArray(new Gson().toJson(pRaceScores,  new TypeToken<RaceScore[]>(){}.getType())));
//    data.put("raceinfo", new JSONObject(new Gson().toJson(raceinfo,  new TypeToken<RaceItemInfo>(){}.getType())));
//    jo.put("data", data);

}
